/**
 * Copyright &copy; 2013-2015 山东易科德软件有限公司 All rights reserved.
 */
package cn.net.ecode.common.persistence;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Map;

import javax.validation.constraints.Pattern;
import javax.xml.bind.annotation.XmlTransient;

import cn.net.ecode.common.config.Global;
import cn.net.ecode.common.persistence.annotation.Id;
import cn.net.ecode.common.supcan.annotation.treelist.SupTreeList;
import cn.net.ecode.common.supcan.annotation.treelist.cols.SupCol;
import cn.net.ecode.common.utils.StringUtils;
import cn.net.ecode.modules.sys.entity.User;
import cn.net.ecode.modules.sys.utils.CorpUtils;
import cn.net.ecode.modules.sys.utils.UserUtils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.collect.Maps;

/**
 * Entity支持类
 * @author ThinkGem
 * @version 2014-8-19
 * @see 数据表中不能以，以下名称命名：
 * 
 * 		page、current_user、sql_map、is_new_record、global、db_name
 * 
 * 		如果必须以，以上名称命名，可在mapper中使用“AS”指定别名。
 */
@SupTreeList
public abstract class BaseEntity<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 实体编号（唯一标识）
	 */
	protected String id;
	
	/**
	 * 实体编号（唯一标识）的字段名
	 */
	protected String idFieldName;

	/**
	 * 归属集团公司Code
	 */
	protected String corpCode;
	
	/**
	 * 归属集团公司Name
	 */
	protected String corpName;
	
	/**
	 * 当前实体分页对象
	 */
	protected Page<T> page;
	
	/**
	 * 当前用户
	 */
	protected User currentUser;
	
	/**
	 * 自定义SQL（SQL标识，SQL内容）
	 */
	protected Map<String, String> sqlMap;

	/**
	 * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	 * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
	 */
	protected boolean isNewRecord = false;
	
	/**
	 * 构造方法
	 */
	public BaseEntity() {
		
	}
	
	/**
	 * 构造方法
	 * @param id 设置主键值
	 */
	public BaseEntity(String id) {
		this();
		setId(id);
	}

	/**
	 * 获取表的主键值，在实体类中的主键get方法上，指定  @Id 注解指定主键。
	 * @return
	 */
	@SupCol(isUnique="true", isHide="true")
	@Pattern(regexp="[a-zA-Z0-9_\\-/]{0,64}", message="编码长度不能超过 64 个字符，并且只能包含字母、数字、下划线、减号、斜杠")
	public String getId() {
		if (this.id == null){
			Method[] ms = getClass().getMethods();
			for (Method m : ms){
				if (m.getName().startsWith("get") && m.getAnnotation(Id.class) != null){
					try {
						// 获取主键值
						String id = (String)m.invoke(this);
						if (id != null){
							if (this.id == null){
								this.id = id;
							}else{
								// 多个主键时，主键值相连。
								this.id += "|" + id;
							}
						}
						// 获取主键字段名
						String fieldName = m.getName().replaceFirst("get", "");
						fieldName = fieldName.replaceFirst(fieldName.substring(0, 1), fieldName.substring(0, 1).toLowerCase());
						if (this.idFieldName == null){
							this.idFieldName = fieldName;
						}else{
							// 多个主键时，主键字段名相连。
							this.idFieldName = "|" + fieldName;
						}
					} catch (Exception e) {
						break;
					}
				}
			}
		}
		return this.id;
	}

	/**
	 * 给主键设置值。
	 * @param id
	 */
	public void setId(String id) {
		Method[] ms = getClass().getMethods();
		for (Method m : ms){
			if (m.getName().startsWith("get") && m.getAnnotation(Id.class) != null){
				try {
					getClass().getMethod("set" + m.getName().substring(3), String.class).invoke(this, id);
					break;
				} catch (Exception e) {
					break;
				}
			}
		}
		this.id = id;
	}
	
	/**
	 * 获取主键的字段名称
	 * @return
	 */
	@JsonIgnore
	public String getIdFieldName() {
		if (this.idFieldName == null){
			this.getId(); // 获取字段名
			if (this.idFieldName == null){
				this.idFieldName = "id";
			}
		}
		return idFieldName;
	}

	/**
	 * 设置主键的字段名称
	 * @return
	 */
	public void setIdFieldName(String idFieldName) {
		this.idFieldName = idFieldName;
	}
	
	/**
	 * 获取归属集团公司Code，取不到获取当前登录用户的集团公司Code
	 * @return
	 */
	@JsonIgnore
	public String getCorpCode() {
		if (corpCode == null){
			corpCode = CorpUtils.getCurrentCorpCode();
		}
		return corpCode;
	}

	/**
	 * 设置归属集团公司Code
	 * @return
	 */
	public void setCorpCode(String corpCode) {
		this.corpCode = corpCode;
	}
	
	/**
	 * 归属集团公司Name，取不到获取当前登录用户的集团公司Name
	 * @return
	 */
	@JsonIgnore
	public String getCorpName() {
		if (corpName == null){
			corpName = CorpUtils.getCurrentCorpName();
		}
		return corpName;
	}

	/**
	 * 设置归属集团公司Name
	 * @return
	 */
	public void setCorpName(String corpName) {
		this.corpName = corpName;
	}

	/**
	 * 获取分页对象
	 * @return
	 */
	@JsonIgnore
	@XmlTransient
	public Page<T> getPage() {
		if (page == null){
			page = new Page<T>();
		}
		return page;
	}
	
	/**
	 * 设置分页对象
	 * @param page
	 * @return
	 */
	public Page<T> setPage(Page<T> page) {
		this.page = page;
		return page;
	}
	
	/**
	 * 获取当前用户对象
	 * @return
	 */
	@JsonIgnore
	@XmlTransient
	public User getCurrentUser() {
		if(currentUser == null){
			currentUser = UserUtils.getUser();
		}
//		// 设置当前用户对象（测试用）
//		if (StringUtils.isBlank(currentUser.getId())) {
//			currentUser.setId("00000000");
//			currentUser.setLoginName("system");
//			currentUser.setNickname("系统管理员");
//		}
		return currentUser;
	}
	
//	/**
//	 * 设置当前用户对象（测试用）
//	 * @param currentUser
//	 */
//	public void setCurrentUser(User currentUser) {
//		this.currentUser = currentUser;
//	}

	/**
	 * 自定义SQL，可在Mybatis中读取这个值。
	 * @return
	 */
	@JsonIgnore
	@XmlTransient
	public Map<String, String> getSqlMap() {
		if (sqlMap == null){
			sqlMap = Maps.newHashMap();
		}
		return sqlMap;
	}

    /**
	 * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	 * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
     * @return
     */
	public boolean getIsNewRecord() {
        return isNewRecord || StringUtils.isBlank(getId());
    }

	/**
	 * 是否是新记录（默认：false），调用setIsNewRecord()设置新记录，使用自定义ID。
	 * 设置为true后强制执行插入语句，ID不会自动生成，需从手动传入。
	 */
	public void setIsNewRecord(boolean isNewRecord) {
		this.isNewRecord = isNewRecord;
	}
	
	/**
	 * 插入之前执行方法，子类实现
	 */
	public void preInsert(){
		
	}
	
	/**
	 * 更新之前执行方法，子类实现
	 */
	public void preUpdate(){
		
	}
	
	/**
	 * 全局变量对象
	 */
	@JsonIgnore
	public Global getGlobal() {
		return Global.getInstance();
	}
	
	/**
	 * 获取数据库类型
	 * @return oracle、mysql、mssql、h2、db2、hsql、postgre、sybase
	 */
	@JsonIgnore
	public String getJdbcName() {
		return Global.getJdbcType();
	}
	
	/**
	 * 获取当前数据库名称(如果数据库类型为highgo，则自动转化为oracle数据库)
	 * @return oracle(highgo)、mysql、mssql、h2、db2、hsql、postgre、sybase
	 */
	@JsonIgnore
	public String getDbName(){
		return Global.getDbName();
	}
	
	/**
	 * 比较两个实体是否相同
	 */
    @Override
    public boolean equals(Object obj) {
        if (null == obj) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (!getClass().equals(obj.getClass())) {
            return false;
        }
        BaseEntity<?> that = (BaseEntity<?>) obj;
        return null == this.getId() ? false : this.getId().equals(that.getId());
    }
    
    /**
     * 输出
     */
    @Override
    public String toString() {
        return getId();//ReflectionToStringBuilder.toString(this);
    }
	
}
